package n10_park_unpark;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.locks.LockSupport;

import static utils.Sleeper.sleep;

/**
 * -------------------------------------------------------
 *                                                       /
 *       线程里park, 其他线程或主线程进行 unpark(线程对象)    /
 *                                                       /
 * =======================================================
 *
 * 与 Object 的 wait & notify 相比
 * 1. wait、notify，notifyAll 必须配合 Object Monitor 一起使用， 而 park 、unpark 不需要
 * 2. park & unpark 是以线程为[单位] 【阻塞】【唤醒】 线程，比较精确
 * 3. notify 随机唤醒一个线程，notifyAll 唤醒所有线程，没那么精确
 * 4. park & unpark 可以先 unpark ，而 wait & notify 不能先 notify
 *
 * @author fu
 * @date 2021-12-25 17:14
 * 概要：
 * XXXXX
 */
@Slf4j(topic = "c.T1")
public class T1_ParkUnpark {

    public static void main(String[] args) {

//        test1();
        test2();
    }

    /**
     * t1线程先park,主线程6秒后unpark(t1)
     * t1线程    ----- 1s 开始park...
     * main线程  ------------------------- 6 秒后unpark ---
     */
    private static void test1(){
        Thread t1 = new Thread(() -> {
            log.debug("start...");
            sleep(1);

            log.debug("1秒后 开始 park......");
            LockSupport.park();

            log.debug("结束 resume...");

        }, "t1");
        t1.start();

        // 2. 主线程
        sleep(6);
        log.debug("6秒后 开始unpark...");
        LockSupport.unpark(t1);
    }

    /**
     * 先执行unpark，将不会停止下来 【unpark 可以在 park之前调用】
     * t1线程    ---------------- 2s 开始park ---
     * main线程  ----- 1s 先unpark
     */
    private static void test2(){
        Thread t1 = new Thread(() -> {
            log.debug("start...");
            sleep(2);

            log.debug("2秒后 开始 park......");
            LockSupport.park();

            log.debug("结束 resume...");

        }, "t1");

        t1.start();

        // 2. 主线程 睡眠一秒 立刻先 unpark ，然后 上面再park()将失效
        sleep(1);
        log.debug("1秒后 开始unpark...");
        LockSupport.unpark(t1);
    }

}
